/**
 * 		-	ad-creatif	-
 * 		-	20/07/2012	-
 *
 * Critical class storing all params of the game. 
 * The player is created there.
 * There's also some tools like loading, saving, pausing, cleaning ram
 * wich will be moved soon
 * 
 **/

package entities {
	
	import blocks.Checkpoint;
	import blocks.GhostZone;
	
	import entities.MeleeAttack;
	
	import org.flixel.FlxG;
	import org.flixel.FlxGame;
	import org.flixel.FlxObject;
	import org.flixel.FlxPoint;
	import org.flixel.FlxSound;
	import org.flixel.FlxSprite;
	import org.flixel.FlxTimer;
	import org.flixel.plugin.photonstorm.FlxControl;
	import org.flixel.plugin.photonstorm.FlxControlHandler;
	import org.flixel.plugin.photonstorm.FlxDelay;
	
	import screens.GameList;
	import screens.GameOver;
	
	import tools.WeaponManager;
	
	public class Player extends Entity {
		
		private var controls:Object = Registry.gameInfos.controls;
		
		private var jumpCount:Number;
		
		public var startX:Number;
		public var startY:Number;
		
		public var checkpoint:Checkpoint;
		public var hitBox:MeleeAttack;
		public var score:Number;
		
		public function Player(X:Number, Y:Number, infos:Object) {
			super(X, Y, infos);
			startX = X;
			startY = Y;
			score=0;
						
			//	Enable the Controls plugin
			if (FlxG.getPlugin(FlxControl) == null)
				FlxG.addPlugin(new FlxControl);
			
			//	Add this sprite to the FlxControl plugin and tell it we want the sprite to accelerate and decelerate smoothly
			FlxControl.create(this, FlxControlHandler.MOVEMENT_ACCELERATES, FlxControlHandler.STOPPING_DECELERATES, 1, true, false);
			
			//	Manage Controls
			if(!controls.upKey) controls.upKey = '' ;		// 'UP'
			if(!controls.downKey) controls.downKey = '' ;	// 'DOWN'
			if(!controls.leftKey) controls.leftKey = ''	;	// 'LEFT'
			if(!controls.rightKey) controls.rightKey = '';	// 'RIGHT'
			if(!controls.jumpKey) controls.upKey = '';		//'SPACE'
			
			
			FlxControl.player1.setCustomKeys(controls.upKey, controls.downKey, controls.leftKey, controls.rightKey);
			FlxControl.player1.setMovementSpeed((infos.gamePlay.acceleration) ? infos.gamePlay.acceleration : 400, 800, infos.gamePlay.speed, 800, (infos.gamePlay.deceleration) ? infos.gamePlay.deceleration : 5000, 0);
			FlxControl.player1.setGravity(0, Registry.gameInfos.world.gravity);
		}
		
		override public function update():void {
			super.update();
			
			if(!active) return;
			
			//  attack
			if(weapon){ 
				if(FlxG.mouse.pressed()) { _attacking = true; weapon.fireAtMouse();}
				if(FlxG.mouse.justReleased()) {_attacking = false; weapon.onFireSound.stop();}
			} else if ( FlxG.mouse.justPressed() && infos.attack.meleeDamage) {
				hitBox = Registry.friendlyPool.recycle(MeleeAttack) as MeleeAttack;
				if(!hitBox) { hitBox = new MeleeAttack(); }
				hitBox.damages = infos.attack.meleeDamage;
				hitBox.setParent(this)
				hitBox.attack();
				if(infos.sounds.attack)infos.sounds.attack.play();
			}

			
			//  animations
			if(justTouched(FLOOR)) {
				if(infos.sounds.hitFloor) infos.sounds.hitFloor.play();
				jumpCount = 0;
			}
			
			
			if(isTouching(FLOOR)){
				if(velocity.x == 0) { //stopped
					if(_attacking) play('attack')
					else if(_crouching) play('crouchIdle');
					else  play('idle');
				} else { //moving
					if(_attacking) play('attackWalk');
					else if(_crouching) play('crouch');
					else if(_charging) play('charge');
					else play('walk');
				}
			} else if(_attacking) play('attack');
			else play('jump');
			
			//  melee attack tracking
			if(hitBox){
				hitBox.x = (facing == RIGHT) ? x+width/2 : x-width/2;
				hitBox.y = y + height/4;
			}
			
			//  specials actions (jump, sprint...)
			if (!_attacking && controls.superAttackKey && FlxG.keys.justPressed(controls.superAttackKey)) abilities.attack('superAttack');
			if (controls.switchWeaponKey && FlxG.keys.justPressed(controls.switchWeaponKey) && weapon) switchWeapon();
			if (controls.jumpKey && FlxG.keys.justPressed(controls.jumpKey) ) {
				if(jumpCount < 1 || (abilities.can('doubleJump') && jumpCount == 1)) {
					jumpCount++; 
					velocity.y = -infos.gamePlay.jumpHeight;
				}
			}
			if (FlxControl.player1.isPressedDown) crouch(true);
			else crouch(false);
			if (controls.sprintKey){
				if( FlxG.keys[controls.sprintKey]) sprint(true);
				if(FlxG.keys.justReleased(controls.sprintKey)) sprint(false);
			}
			
		}
		
		
		
		/**
		 * 
		 * this override will check if the player is outside the game borders limits 
		 * and then will kill him, block him or launch next level if defined though
		 * 
		 * */
		override public function postUpdate():void{
			super.postUpdate();
			
			if (x < 0 - width/2 && !switchGame(Registry.gameInfos.world.prevLevel))
				x = 0;
			
			else if (x > Registry.level.ground.width - width && !switchGame(Registry.gameInfos.world.nextLevel))
				x = Registry.level.ground.width - infos.tile.tileSize[0];
			
			if (y > Registry.level.ground.height) 
				kill();
		}
	
		
		
		override public function kill():void {
			if (infos.gamePlay.lives > 0) {
				x = checkpoint ? checkpoint.x : Registry.gameInfos.world.startPos[0] * Registry.level.tileSize[0];
				y = checkpoint ? checkpoint.y - height : Registry.gameInfos.world.startPos[1] * Registry.level.tileSize[1];
				health = 100;
				velocity.x = velocity.y = 0
				score = 0;
				infos.gamePlay.lives--;
			} else {
				FlxG.switchState(new GameOver);
			}
		}
				
		
		private function crouch(value:Boolean):void {
			if (_crouching == value) return;
			_crouching = value;
			
			var ratio:Number = infos.tile.realSize[1] * .5
			
			if (!_crouching && !isTouching(CEILING)) {
				maxVelocity.x = infos.gamePlay.speed;
				height = infos.tile.realSize[1];
				offset.y = infos.tile.offset[1];
				y -= ratio;
			} else {
				maxVelocity.x = infos.gamePlay.speed - 20;
				height = infos.tile.realSize[1] - ratio;
				offset.y = parseInt(infos.tile.offset[1]) + ratio;
				y += ratio;
			}
		}
		
		
		private function sprint(value:Boolean):void {
			if (_charging == value) return;
			_charging = value;
			if (!_charging) {
				maxVelocity.x = infos.gamePlay.speed; //set increased max velocity
			} else {
				//acceleration.x = 0; //set acceleration to 0, so the player slows down due to drag
				maxVelocity.x = infos.gamePlay.speed *2; //reset max velocity to orginal value
			}
		}
		
		
		private function switchWeapon():void {
			var weapons:Array = infos.attack.weaponsName;
			var weaponIndex:uint = weapons.indexOf(weapon.name);
			var newWeaponName:String = weapons[weaponIndex + 1] ? weapons[weaponIndex + 1] : weapons[0];
			weapon = WeaponManager.addWeapon(newWeaponName, this);
		}
		
		
		private function switchGame(gameName:String=null):Boolean {
			// gameName is null for the first and the last level or if the gameName isn't found
			if (!gameName || !Registry.gameList[gameName])
				return false;
			
			Registry.erase();
			Registry.gameName = gameName;
			Registry.gameList[gameName].score = score;
			Registry.gameList[gameName].level = level;
			Registry.gameList[gameName].lives = infos.gamePlay.lives;
			
			FlxG.switchState(new GameOver);
			
			return true;
		}
	}
}
